﻿using RestApp.BusinessLogic.Abstract;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
using RestApp.BusinessLogic.Code;

namespace RestApp.BusinessLogic
{
    public class JobFactsLogic : BaseLogic<FactOfWork>, IJobFacts
    {
        //отрефакторить бы
        public override void Add(FactOfWork item)
        {
            using (var context = new RestAppEntities())
            {
                using (var transaction = context.Database.BeginTransaction())
                {
                    try
                    {
                        var currentGrafik = context
                            .WorkGraphics
                            .Include(t => t.User)
                            .FirstOrDefault(t => t.Id == item.IdWorkGraphic);

                        if (currentGrafik == null)
                        {
                            throw new InvalidOperationException("no work grafik with id " + item.IdWorkGraphic);
                        }

                        //-
                        decimal oneMinutePenalty = 2;
                        //int dinnerTime = 60;
                        //-
                        WorkTimeFormatter formatter = new WorkTimeFormatter();
                        TimeSpan grafikWorkMinutes = formatter.GetWorkTime(currentGrafik.StartTime.Value, currentGrafik.EndTime.Value);
                       // TimeSpan grafikWorkMinutes = currentGrafik.EndTime.Value - currentGrafik.StartTime.Value;
						int workMinutes = (int)grafikWorkMinutes.TotalMinutes;// -dinnerTime;

                        decimal oneMinuteCost = currentGrafik.User.Salary / 60;
                        decimal mustBePayd = workMinutes * oneMinuteCost;

                        if(item.NoWork != null && item.NoWork.Value)
                        {
                            NoWork(context, item, currentGrafik.IdUser.Value, mustBePayd);
                            transaction.Commit();
                            return;
                        }

                        decimal penalties = 0;
                        string penaltyComment = "";

                        if (item.TimeStart > currentGrafik.StartTime.Value)
                        {
                            TimeSpan delayTime = item.TimeStart - currentGrafik.StartTime.Value;
                            int firedMinutes = (int)delayTime.TotalMinutes;
                            penalties += firedMinutes * oneMinutePenalty;
                            penaltyComment += string.Format("Пришел на работу позднее на {0:hh\\:mm}\n", delayTime);
                        }

                        if (item.TimeEnd < currentGrafik.EndTime.Value)
                        {
                            TimeSpan beforeGoTime = currentGrafik.EndTime.Value - item.TimeEnd;
                            int beforeTimeMinutes = (int)beforeGoTime.TotalMinutes;
                            penalties += beforeTimeMinutes * oneMinutePenalty;
                            penaltyComment += string.Format("Ушел с работы раньше на {0:hh\\:mm}\n", beforeGoTime);
                        }


                        decimal factPay = 0;
                        decimal factPayTmp = mustBePayd - penalties;

                        if (factPayTmp > 0)
                        {
                            factPay = factPayTmp;
                        }

                        factPay = Math.Abs(factPay);

                        if (item.IsReasondForWorkCancelation != null && item.IsReasondForWorkCancelation.Value)
                        {
                            ReasonCancelation(context, item, currentGrafik.IdUser.Value, mustBePayd, mustBePayd);
                            transaction.Commit();
                            return;
                        }

                        Payment pay = new Payment();
                        pay.Comment = penaltyComment;
                        pay.FactPay = factPay;
                        pay.IdUser = currentGrafik.IdUser;
                        pay.MustBePay = mustBePayd;
                        pay.Penalties = penalties;

                        context.Payments.Add(pay);
                        context.SaveChanges();

                        item.Id = pay.Id;
                        context.FactOfWorks.Add(item);
                        context.SaveChanges();

                        transaction.Commit();
                    }
                    catch (Exception)
                    {
                        transaction.Rollback();
                    }
                }
            }
        }

        private void ReasonCancelation(RestAppEntities context, FactOfWork item, int idUser, decimal mustPayed, decimal factPay)
        {
            BadWork(context, item, idUser, mustPayed, "Уважительная причина отсутствия: " + item.Comment, factPay);
        }

        private void NoWork(RestAppEntities context, FactOfWork item, int idUser, decimal mustPayed)
        {
            BadWork(context, item, idUser, mustPayed, "Прогул сотрудника." + item.Comment, -mustPayed, mustPayed);
        }

        private void BadWork(RestAppEntities context, FactOfWork item, int idUser, decimal mustPayed, string comment,decimal factPay = 0, decimal penalties = 0)
        {
            Payment pay = new Payment();
            pay.Comment = comment;
            pay.FactPay = factPay;
            pay.IdUser = idUser;
            pay.MustBePay = mustPayed;
            pay.Penalties = penalties;

            context.Payments.Add(pay);
            context.SaveChanges();

            item.Id = pay.Id;
            context.FactOfWorks.Add(item);
            context.SaveChanges();
        }

        public FactOfWork GetByGraphicId(int idGraphic)
        {
            using (var context = new RestAppEntities())
            {
                return context
                    .FactOfWorks
                    .Include(t => t.Payment)
                    .FirstOrDefault(t => t.IdWorkGraphic == idGraphic);
            }
        }
    }
}
